package org.telegram.bot.base;

import com.ruoyi.common.enums.StatusEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.spring.SpringUtils;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.springframework.stereotype.Component;
import org.telegram.bot.domain.BotInfo;
import org.telegram.bot.service.IBotInfoService;
import org.telegram.telegrambots.client.okhttp.OkHttpTelegramClient;
import org.telegram.telegrambots.longpolling.BotSession;
import org.telegram.telegrambots.longpolling.TelegramBotsLongPollingApplication;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import org.telegram.telegrambots.meta.generics.TelegramClient;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: wyx
 * @Date: 2023/5/28 14:08
 */
@Slf4j
@Component
public class BotRegisterApplication {

    @Resource
    private TelegramBotsLongPollingApplication telegramBotsApplication;

    @Resource
    private OkHttpClient okClient;

    @Resource
    private IBotInfoService botInfoService;

    /**
     * 机器人的缓存，使用 ConcurrentHashMap 提高并发性能
     */
    private static final Map<String, BotInfo> botInfoMaps = new ConcurrentHashMap<>();

    public BotRegisterApplication() {
        // 使用 SpringUtils 获取 Bean，确保依赖注入正确
        botInfoService = SpringUtils.getBean(IBotInfoService.class);
        // 初始化时注册所有机器人
        botInfoMaps.putAll(botInfoService.selectList4Register());
    }

    /**
     * 注册所有机器人
     */
    @PostConstruct
    public void registerBot() {
        // 遍历所有开启的机器人
        for (Map.Entry<String, BotInfo> entry : botInfoMaps.entrySet()) {
            String botId = entry.getKey();
            BotInfo botInfo = entry.getValue();
            try {
                botInfo.setBot(build(botInfo.getToken(), botId));
                botInfoMaps.put(botId, botInfo);
                log.info("注册成功机器人:{},{}", botInfo.getId(), botInfo.getBotName());
            } catch (TelegramApiException e) {
                log.error("注册失败机器人:{},{} - {}", botInfo.getId(), botInfo.getBotName(), e.getMessage());
                // 状态改为停用
                botInfo.setStatus(StatusEnum.DISABLE.getCode());
                botInfoService.updateBotStatus(botInfo);
                // 删除失效的机器人
                botInfoMaps.remove(botId);
            }
        }
    }

    /**
     * 新增机器人
     */
    public BotInfo registerBot(BotInfo botInfo) throws TelegramApiException {
        botInfo.setBot(build(botInfo.getToken(), botInfo.getId()));
        if (botInfo.getBot().getBotSession() == null) {
            throw new ServiceException("机器人状态异常");
        }
        // 存入 map
        botInfoMaps.put(botInfo.getId(), botInfo);
        if (StatusEnum.DISABLE.getCode().equals(botInfo.getStatus())) {
            botInfo.getBot().getBotSession().stop();
        }
        return botInfo;
    }

    /**
     * 改变机器人状态
     *
     * @param botInfo 包含机器人ID和新状态的 BotInfo 对象
     */
    public void updateStatus(BotInfo botInfo) throws TelegramApiException {
        BotInfo mBot = botInfoMaps.get(botInfo.getId());
        if (mBot == null) {
            mBot = registerBot(botInfo);
        } else {
            // 判断是否在运行
            if (mBot.getBot().getBotSession().isRunning()) {
                mBot.getBot().getBotSession().stop();
            }
        }
        if (mBot.getBot().getBotSession() == null) {
            throw new ServiceException("机器人状态异常");
        }
        // 加到 map 中
        botInfoMaps.put(mBot.getId(), mBot);
        // 根据新状态启动或停止机器人
        if (StatusEnum.OK.getCode().equals(botInfo.getStatus()) && !mBot.getBot().getBotSession().isRunning()) {
            mBot.getBot().getBotSession().start();
        } else if (StatusEnum.DISABLE.getCode().equals(botInfo.getStatus()) && mBot.getBot().getBotSession().isRunning()) {
            mBot.getBot().getBotSession().stop();
        }
    }

    /**
     * 构建 CustomSpringLongPollingBot 实例
     *
     * @param token  机器人的 Token
     * @param botId  机器人的 ID
     * @return 构建好的 CustomSpringLongPollingBot 实例
     * @throws TelegramApiException 如果构建过程中发生异常
     */
    private CustomSpringLongPollingBot build(String token, String botId) throws TelegramApiException {
        TelegramClient telegramClient = new OkHttpTelegramClient(okClient, token);
        CustomSpringLongPollingBot customSpringLongPollingBot = new CustomSpringLongPollingBot(telegramClient, token, botId);
        BotSession botSession = telegramBotsApplication.registerBot(token, customSpringLongPollingBot);
        customSpringLongPollingBot.setBotSession(botSession);
        return customSpringLongPollingBot;
    }

    /**
     * 获取指定 ID 的机器人信息
     *
     * @param botId 机器人的 ID
     * @return 对应的 BotInfo 对象，如果不存在则返回 null
     */
    public static BotInfo getBotInfo(String botId) {
        return botInfoMaps.get(botId);
    }
}
